package br.unicamp.ic.inf312.arena.persistencia.dao.impl;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLData;
import java.sql.SQLInput;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;

import com.mysql.jdbc.ResultSet;

import br.unicamp.ic.inf312.arena.modelo.controleacesso.Perfil;
import br.unicamp.ic.inf312.arena.modelo.controleacesso.UsuarioSistema;
import br.unicamp.ic.inf312.arena.modelo.pessoa.Funcionario;
import br.unicamp.ic.inf312.arena.modelo.pessoa.Pessoa;
import br.unicamp.ic.inf312.arena.persistencia.dao.IUsuarioPerfilDAO;
import br.unicamp.ic.inf312.framework.persistencia.SQLUtil;

/*
 * ArenaTicketMain - Venda de Bilhetes Eletronicos para Espetaculos (Arena Entretenimento S.A.)
 * UsuarioPerfilDAOMySQL.java
 * ©2006
 */

/**
 * @author  inf312
 */
public class UsuarioPerfilDAOMySQL implements IUsuarioPerfilDAO {

	/**
	 * Valida se eh um usuario cadastrado e efetuou logon corretamente.
	 *
	 * @param br.unicamp.ic.inf312.arena.modelo.controleacesso.UsuarioSistema
	 *
	 * @return int {0 - usuario nao encontrado, caso contrario retorna o nivel de acesso
	 * associado ao perfil deste usuario}
	 *
	 * @throws Exception 
	 */
	//TODO: Alteracao para a ativ. 2
	public UsuarioSistema validarLogon(UsuarioSistema usuario) throws Exception {
		
		// verifica se existe usuario com mesmo login
		UsuarioSistema usuarioAut = this.getUsuario( usuario.getLogin() );
		
		// verifica se as informacoes de login estao corretas
		if ( null != usuarioAut && usuarioAut.getSenha().equals( usuario.getSenha() ))
		{
			// usuario validado: adiciona o perfil
			usuarioAut.setPerfil( this.getPerfil( usuarioAut.getCodPerfil() ) );
		}
		// informacoes incorretas: invalida o usuario  
		else
			usuarioAut = null;
			
		return ( usuarioAut );
	}
	
	//TODO: Alteracao para a ativ. 1
	//-------------------------------------------------
	public List<UsuarioSistema> getUsuariosPorFiltro(String filtro) throws Exception
	//-------------------------------------------------
	{		
		StringBuilder strQuery = new StringBuilder("SELECT * FROM usuario WHERE UPPER(login) LIKE ?");
		
		return ( this.carregarPerfil( SQLUtil.select(strQuery.toString(), UsuarioSistema.class, new String[]{filtro + "%"} )));
	}
	
	//-------------------------------------------------
	public List<UsuarioSistema> getAllUsuarios() throws Exception
	//-------------------------------------------------
	{
		return ( this.carregarPerfil(SQLUtil.selectAll("usuario", UsuarioSistema.class )));		
	}
	
	//-------------------------------------------------
	public boolean removerUsuario(UsuarioSistema usuario) throws Exception
	//-------------------------------------------------
	{
		
		return ( (SQLUtil.update("DELETE FROM usuario WHERE codusuario = ?", new Object[]{ usuario.getCodUsuario() }) > 0) &&
				 (SQLUtil.update("DELETE FROM pessoa WHERE codpessoa = ?", new Object[]{ usuario.getCodPessoa() }) > 0) );		
	}

	//-------------------------------------------------
	public List<Perfil> getAllPerfis() throws Exception
	//-------------------------------------------------
	{
		return ( SQLUtil.selectAll("perfil", Perfil.class));
	}
	
	//-------------------------------------------------
	public boolean adicionarUsuario(UsuarioSistema usuario) throws Exception
	//-------------------------------------------------
	{
		CallableStatement procInserir = SQLUtil.getConnection().prepareCall("{ call inserirUsuario(?, ?, ?, ?, ?, ?, ?) }");

		//nome
		procInserir.setString(1, usuario.getNome());
		
		// documento
		if ( null != usuario.getDocumento() )
			procInserir.setString(2, usuario.getDocumento());
		else
			procInserir.setNull(2, Types.VARCHAR);
		
		// data nascimento
		if ( null != usuario.getDataNascimento() )
			procInserir.setDate(3, new java.sql.Date(usuario.getDataNascimento().getTime()));
		else
			procInserir.setNull(3, Types.DATE);
		
		// departamento
		if ( null != usuario.getDepartamento() )
			procInserir.setString(4, usuario.getDepartamento());
		else
			procInserir.setNull(4, Types.VARCHAR);
		
		//login
		procInserir.setString(5, usuario.getLogin());
		
		//senha
		procInserir.setString(6, usuario.getSenha());
		
		//perfil
		procInserir.setInt(7, usuario.getPerfil().getCodPerfil());
		
		//executa a procedure
		procInserir.execute();
		
		return ( procInserir.getUpdateCount() > 0 );
	}
	
	
	//-------------------------------------------------
	private List<UsuarioSistema> carregarPerfil(List<UsuarioSistema> usuarios ) throws Exception
	//-------------------------------------------------
	{
		// obtem a lista de perfis cadastrados
		List<Perfil> perfis = getAllPerfis();
		
		// adiciona o perfil de cada usuario da lista
		for ( UsuarioSistema usuario : usuarios )
			for ( Perfil perfil : perfis )
				if ( usuario.getCodPerfil() == perfil.getCodPerfil())
				{
					usuario.setPerfil(perfil);
					
					//obtem as informacoes de funcionario
					Funcionario funcionario = this.getFuncionario(usuario.getCodPessoa());
					usuario.setNome(funcionario.getNome());
					usuario.setDataNascimento(funcionario.getDataNascimento());
					usuario.setDepartamento(funcionario.getDepartamento());
					
					break;
				}
		
		return ( usuarios );
	}
	
	//-------------------------------------------------
	private Funcionario getFuncionario( int codPessoa ) throws Exception
	//-------------------------------------------------
	{
		return ((Funcionario) SQLUtil.retrieveBean( "SELECT * from pessoa WHERE codpessoa = ?", Funcionario.class, new Object[]{ codPessoa } ));		
	}
	
	//-------------------------------------------------
	private Perfil getPerfil( int codPerfil ) throws Exception
	//-------------------------------------------------
	{
		return ((Perfil) SQLUtil.retrieveBean( "SELECT * from perfil WHERE codperfil = ?", Perfil.class, new Object[]{ codPerfil } ));
	}
	
	//-------------------------------------------------
	private UsuarioSistema getUsuario( String login ) throws Exception
	//-------------------------------------------------
	{
		return ( (UsuarioSistema) SQLUtil.retrieveBean( "SELECT * from usuario WHERE login = ?", UsuarioSistema.class, new Object[]{ login } ));
	}
}